﻿using System;
using System.Diagnostics;
using System.IO;
using Microsoft.Data.Schema.SchemaModel;
using Microsoft.Data.Schema.Sql.SchemaModel;
using Microsoft.Data.Schema.StaticCodeAnalysis;
using Microsoft.Data.Schema;
using System.Collections;
using System.Collections.Generic;

using System.Globalization;
using Microsoft.Data.Schema.Extensibility;
using Microsoft.Data.Schema.ScriptDom.Sql;
using Microsoft.Data.Schema.Sql;

namespace Neznayka
{
    public static class SqlCheck
    {

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
        public static bool HasNoFromClause(MergeStatement node)
        {
            //silence compiler warnings 
            if (node.FirstTokenIndex == 0) { }
            //return (node.TableSource != null);
            return false;
        }
        public static bool HasNoFromClause(DeleteStatement node)
        {
            return( ( node.FromClauses == null )
                    ||
                    ( ( node.FromClauses != null ) && 
                      ( node.FromClauses.Count == 0 )
                    )
                  );
        }
        public static bool HasNoFromClause(UpdateStatement node)
        {
            return ((node.FromClauses == null)
                    ||
                    ((node.FromClauses != null) &&
                      (node.FromClauses.Count == 0)
                    )
                  );
        }
        public static bool HasNoFromClause(QuerySpecification node)
        {
            return ((node.FromClauses == null)
                    ||
                    ((node.FromClauses != null) &&
                      (node.FromClauses.Count == 0)
                    )
                  );
        }

        public static bool HasFromClause(MergeStatement node)
        {
            return (!HasNoFromClause(node));
        }
        public static bool HasFromClause(DeleteStatement node)
        {
            return (!HasNoFromClause(node));
        }
        public static bool HasFromClause(UpdateStatement node)
        {
            return (!HasNoFromClause(node));
        }
        public static bool HasFromClause(QuerySpecification node)
        {
            return (!HasNoFromClause(node));
        }


        //public static bool HasOneFromClauseSource(MergeStatement node)
        //{
        //    //return (node.TableSource != null);
        //    return true;
        //}
        //// tricky if there is no from clause there is still exactly one tabe involved
        //public static bool HasOneFromClauseSource(DeleteStatement node)
        //{
        //    return( ( node.FromClauses != null ) && 
        //            ( node.FromClauses.Count == 1 )
        //          );
        //}
        //// tricky if there is no from clause there is still exactly one tabe involved
        //public static bool HasOneFromClauseSource(UpdateStatement node)
        //{
        //    return( ( node.FromClauses != null ) && 
        //            ( node.FromClauses.Count == 1 )
        //          );
        //}
        //public static bool HasOneFromClauseSource(QuerySpecification node)
        //{
        //    return( ( node.FromClauses != null ) && 
        //            ( node.FromClauses.Count == 1 )
        //          );
        //}

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
        public static bool HasExactlyOneFromClauseTableSource(MergeStatement node)
        {
            //silence compiler warnings 
            if (node.FirstTokenIndex == 0) { }
            return false;
//            return ((node.TableSource != null) &&
//                    (node.TableSource is Microsoft.Data.Schema.ScriptDom.Sql.TableSourceWithAlias)
//                  );
        }
        // tricky if there is no from clause there is still exactly one tabe involved
        // in the context in which it is used - it literally means just the 1
        public static bool HasExactlyOneFromClauseTableSource(DeleteStatement node)
        {
            return (    (   ( node.FromClauses != null ) && 
                            ( node.FromClauses.Count == 1 ) &&
                            ( node.FromClauses[0]  is Microsoft.Data.Schema.ScriptDom.Sql.TableSourceWithAlias )
                        )
                  );
        }
        //// tricky if there is no from clause there is still exactly one tabe involved
        //// not used in any  context - eliminate for now
        //public static bool HasExactlyOneFromClauseTableSource(UpdateStatement node)
        //{
        //    return (((node.FromClauses != null) &&
        //                    (node.FromClauses.Count == 1) &&
        //                    (node.FromClauses[0] is Microsoft.Data.Schema.ScriptDom.Sql.TableSourceWithAlias)
        //                )
        //          );
        //}
        public static bool HasExactlyOneFromClauseTableSource(QuerySpecification node)
        {
            return( ( node.FromClauses != null ) && 
                    ( node.FromClauses.Count == 1 ) &&
                    ( node.FromClauses[0]  is Microsoft.Data.Schema.ScriptDom.Sql.TableSourceWithAlias )
                  );
        }


        // For this helper method - at most means any table source at all
        // Semantics are shite aren't they
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
        public static bool HasAtMostOneTableSource(MergeStatement node)
        {
            //silence compiler warnings 
            if (node.FirstTokenIndex == 0) { }
            //return (node.TableSource != null);
            return false;
        }

        // tricky if there is no from clause there is still exactly one tabe involved
        public static bool HasAtMostOneTableSource(DeleteStatement node)
        {
            return (    (node.FromClauses == null) 
                     ||
                        (  (node.FromClauses != null) &&
                           (node.FromClauses.Count == 0)
                        )
                     || 
                        (  (node.FromClauses.Count == 1) &&
                           (node.FromClauses[0] is Microsoft.Data.Schema.ScriptDom.Sql.TableSourceWithAlias)
                        )
                  );
        }
        // tricky if there is no from clause there is still exactly one tabe involved
        public static bool HasAtMostOneTableSource(UpdateStatement node)
        {
            return ((node.FromClauses == null)
                     ||
                        ((node.FromClauses != null) &&
                           (node.FromClauses.Count == 0)
                        )
                     ||
                        ((node.FromClauses.Count == 1) &&
                           (node.FromClauses[0] is Microsoft.Data.Schema.ScriptDom.Sql.TableSourceWithAlias)
                        )
                  );
        }
        public static bool HasAtMostOneTableSource(QuerySpecification node)
        {
            return ((node.FromClauses == null)
                     ||
                        ((node.FromClauses != null) &&
                           (node.FromClauses.Count == 0)
                        )
                     ||
                        ((node.FromClauses.Count == 1) &&
                           (node.FromClauses[0] is Microsoft.Data.Schema.ScriptDom.Sql.TableSourceWithAlias)
                        )
                  );
        }

        ////////////////////////////

        // For this helper method - at most means any table source at all
        // Semantics are shite aren't they
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
        public static bool HasAtLeastOneTableSource(MergeStatement node)
        {
            //silence compiler warnings 
            if (node.FirstTokenIndex == 0) { }
            //return (node.TableSource != null);
            return true;
        }

        // tricky if there is no from clause there is still exactly one tabe involved
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
        public static bool HasAtLeastOneTableSource(DeleteStatement node)
        {
            //silence compiler warnings 
            if (node.FirstTokenIndex == 0) { }
            return true;
        }
        // tricky if there is no from clause there is still exactly one tabe involved
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
        public static bool HasAtLeastOneTableSource(UpdateStatement node)
        {
            //silence compiler warnings 
            if (node.FirstTokenIndex == 0) { }
            return true;
        }
        public static bool HasAtLeastOneTableSource(QuerySpecification node)
        {
            return (((node.FromClauses != null) &&
                           (node.FromClauses.Count > 0)
                        )
                  );
        }

        ////////////////////////////
        
        ///

        public static bool HasNoIntoClause(QuerySpecification node)
        {
            return (  (node.Into == null)
                    ||
                      (
                        (node.Into != null) &&
//                        (node.Into.BaseIdentifier.Value == "")
                        (String.IsNullOrEmpty(node.Into.BaseIdentifier.Value))
                      )
                  );
        }

        public static bool HasIntoClause(QuerySpecification node)
        {
            return !HasNoIntoClause(node);
        }
    }
}